﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace JiGBot.Classes
{
    class Reader
    {
        [DllImport("kernel32.dll")]
        public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
            [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);

        #region Memory Reading Functions
        public byte[] ReadBytes(IntPtr Handle, Int64 Address, uint BytesToRead)
        {
            IntPtr ptrBytesRead;
            byte[] buffer = new byte[BytesToRead];
            ReadProcessMemory(Handle, new IntPtr(Address), buffer, BytesToRead, out ptrBytesRead);
            return buffer;
        }
        public byte ReadByte(Int64 Address, IntPtr? Handle = null)
        {
            return ReadBytes(getIntPtr(Handle), Address, 1)[0];
        }
        public string ReadBool(Int64 Address, uint length, IntPtr? Handle = null)
        {
            return BitConverter.ToString(ReadBytes(getIntPtr(Handle), Address, length), 0);
        }
        public int ReadInt32(long Address, uint length = 4, IntPtr? Handle = null)
        {
            return BitConverter.ToInt32(ReadBytes(getIntPtr(Handle), Address, length), 0);
        }
        public ushort ReadInt16(long Address, IntPtr? Handle = null)
        {
            return BitConverter.ToUInt16(ReadBytes(getIntPtr(Handle), Address, 2), 0);
        }
        public double ReadDouble(long Address, IntPtr? Handle = null)
        {
            return BitConverter.ToDouble(ReadBytes(getIntPtr(Handle), Address, 8), 0);
        }
        public string ReadString(long Address, uint length = 32, IntPtr? Handle = null)
        {
            string temp3 = ASCIIEncoding.Default.GetString(ReadBytes(getIntPtr(Handle), Address, length));
            string[] temp3str = temp3.Split('\0');
            return temp3str[0];
        }
        public UInt32 ReadPtr(long Address, UInt32[] offsets, uint length = 32, IntPtr? Handle = null)
        {
            UInt32 Addr = (UInt32)ReadInt32(Address + (long)Util.Tibia.MainModule.BaseAddress);
            UInt32 NewAddr = Addr;
            int i = 0;
            foreach (UInt32 offset in offsets)
            {
                if (i != offsets.Length - 1)
                {
                    NewAddr = (UInt32)ReadInt32(NewAddr + offset);
                }
                else
                {
                    return NewAddr + offset;
                }
                i++;
            }
            return NewAddr;
        }
        public string ReadStringPtr(long Address, UInt32[] offsets, uint length = 32, IntPtr? Handle = null)
        {
            UInt32 Addr = (UInt32)ReadInt32(Address + (long)Util.Tibia.MainModule.BaseAddress);
            UInt32 NewAddr = Addr;
            int i = 0;
            foreach (UInt32 offset in offsets)
            {
                if (i != offsets.Length)
                {
                    NewAddr = (UInt32)ReadInt32(NewAddr + offset);
                }
                i++;
            }
            return ReadString(NewAddr, 255);
        }

        public IntPtr getIntPtr(IntPtr? Handle)
        {
            if (Handle == null)
            {
                return Util.Tibia.Handle;
            }
            else
            {
                return (IntPtr)Handle;
            }

        }
        #endregion
    }
}
